home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_300 / 399_01 / mined.doc < prev    next >
Encoding:
Text File  |  1993-08-03  |  22.2 KB  |  431 lines

  1. +=====================================================================+
  2. |        Documentation file of the Mined editor.               |
  3. +=====================================================================+
  4.  
  5.  Author: Michiel Huisjes.
  6.  
  7.  Modified by Achim Mⁿller to run on a Unix machine with VT100-like
  8.  terminals attached and to recognize function key character sequences.
  9.  
  10.  Modifications and corrections made by Thomas Wolff:
  11.     Basic capabilities:
  12.     Runs with arbitrary terminals on UNIX (using termcap).
  13.     Responds correctly to changes of window size, including
  14.         redisplay of status line; keeps position in text.
  15.     Accepts and displays an 8 bit character set.
  16.     User interface:
  17.     Two letter ESCAPE commands are used for less frequent functions.
  18.     The concept of a HOP key prefix was introduced which fortifies
  19.         any positioning function that follows. This provides more
  20.         command flexibility without too much need of key remembering.
  21.     Command key layout changed to resemble WordMaster/WordStar.
  22.     Improved behaviour:
  23.     Stripping off lines too long for the screen implemented
  24.         also on status line output. If status line input overflows
  25.         the screen and wraps/scrolls, the screen is redisplayed.
  26.     Search displays a "wrap around end of file" message for
  27.         better orientation.
  28.     In case of system errors, the appropriate error message
  29.         is fetched and displayed instead of printing
  30.         numerical hieroglyphs or indistinguished
  31.         commonplace messages (as many UNIX commands do).
  32.     Additional features and commands:
  33.     A HELP command.
  34.     A SUSPEND command with automatic file saving.
  35.     A repeat search command.
  36.     A replace command with confirmation dialogue.
  37.     A change working directory command.
  38.     A change file name reference command.
  39.     Reading from standard input and writing to standard output.
  40.     Starting up at a given line number.
  41.     Appending versions of the buffer cut/copy/write commands.
  42.     Process-independent version of the paste command, thus enabling
  43.         inter-window paste operations.
  44.     A view only version of the edit command (not yet very well developed).
  45.     Commands to print buffer / to perform command with buffer as input.
  46.     Positioning to a percentage within the text.
  47.     Accepts control char sequence for absolute positioning (by mouse)
  48.     Multi-file edit
  49.     External interrupt handling with attempts to save the text
  50.     Configurable indicators for line shift left/right, line end, tab.
  51.     Improved text security:
  52.     Doesn't quit if a file save fails or even if the question for
  53.         a filename isn't answered. So you have a chance
  54.         to try another filename or something.
  55.     Asks whether to overwrite file whenever a file is to be
  56.         written to which was not previously read in.
  57.     Removed abort_mined since no one wants to kill an editor
  58.         unconditionally without attempt to save the text.
  59.     Corrections:
  60.     Some screen positioning errors and inconsistencies
  61.         have been eliminated, for example:
  62.     The EF function now really positions to the end of the text, not
  63.         to the beginning of the last line,
  64.     The HIGH and LOW functions now stay in the current screen column,
  65.         as UP and DN do now more consistently.
  66.     Input routine detects overflow of input buffer.
  67.     Doesn't crash if a file loaded or inserted contains NULL chars.
  68.     Scratch file counting and deleting was corrected.
  69.     The Readonly flag and status message is now based on the really
  70.         effective circumstances (could show wrong state before if
  71.         real and effective user id were different).
  72.     Several minor modifications, e.g.: XBREAK (the screen column limit)
  73.         was increased by 1, since two columns were left blank on
  74.         the right screen border.
  75.     Missing modification:
  76.         The rightmost screen column is currently unused because
  77.         linefeed is used as a line positioner. If absolute
  78.         positioning would be added for each text line output,
  79.         the screen column limit XBREAK could again be increased by 1.
  80.  
  81.     Many further improvements, including special MSDOS adaptations, not 
  82.     further described here. See the help file for information about 
  83.     mined's features.
  84.  
  85.  1. General remarks.
  86.  
  87.     Mined is a screen editor designed for the minix operating system.
  88.     It is meant to be used on files not larger than 50K and to be fast.
  89.     When mined starts up, it reads the file into its memory to minimize
  90.     disk access. The only time that disk access is needed is when certain
  91.     save, write or copy commands are given.
  92.  
  93.     Mined has the style of Emacs or Jove, that means that there are no modes.
  94.     Each character has its own entry in an 256 pointer to function array,
  95.     which is called when that character is typed. Only ASCII characters are
  96.     connected with a function that inserts that character at the current
  97.     location in the file. Two exceptions are <linefeed> and <tab> which are
  98.     inserted as well. Note that the mapping between commands and functions
  99.     called is implicit in the table. Changing the mapping just implies
  100.     changing the pointers in this table.
  101.  
  102.     The display consists of SCREENMAX + 1 lines and XMAX + 1 characters. When
  103.     a line is larger (or gets larger during editing) than XBREAK characters,
  104.     the line is either shifted SHIFT_SIZE characters to the left (which means
  105.     that the first SHIFT_SIZE characters are not printed) or the end of the
  106.     line is marked with the SHIFT_MARK character and the rest of the line is
  107.     not printed.  A line can never exceed MAX_CHARS characters. Mined will
  108.     always try to keep the cursor on the same line and same (relative)
  109.     x-coordinate if nothing changed. So if you scroll one line up, the cursor
  110.     stays on the same line, or when you move one line down, the cursor will
  111.     move to the same place on the line as it was on the previous.
  112.     Every character on the line is available for editing including the
  113.     linefeed at the the of the line. When the linefeed is deleted, the current
  114.     line and the next line are joined. The last character of the file (which
  115.     is always a linefeed) can never be deleted.
  116.     The bottomline (as indicated by YMAX + 1) is used as a status line during
  117.     editing. This line is usually blank or contains information mined needs
  118.     during editing. This information (or rather questions) is displayed in
  119.     reverse video.
  120.  
  121.     The terminal modes are changed completely. All signals like start/stop,
  122.     interrupt etc. are unset. The only signal that remains is the quit signal.
  123.     The quit signal (^\) is the general abort signal for mined. Typing a ^\
  124.     during searching or when mined is asking for filenames, etc. will abort
  125.     the function and mined will return to the main loop.
  126.     Sending a quit signal during the main loop will abort the session
  127.     (after confirmation) and the file is not (!) saved. *removed*
  128.     The session will also be aborted when an unrecoverable error occurs, e.g.
  129.     when there is no more memory available. If the file has been modified,
  130.     mined will ask if the file has to be saved or not.
  131.     If there is no more space left on the disk, mined will just give an error
  132.     message and continue.
  133.  
  134.     The number of system calls are minimized. This is done to keep the editor
  135.     as fast as possible. I/O is done in SCREEN_SIZE reads/writes. Accumulated
  136.     output is also flushed at the end of each character typed.
  137.  
  138.  2. Regular expressions
  139.  
  140.     Mined has a built in regular expression matcher, which is used for
  141.     searching and replace routines. A regular expression consists of a
  142.     sequence of:
  143.  
  144.     1. A normal character matching that character.
  145.     2. A . matching any character.
  146.     3. A ^ matching the begin of a line.
  147.     4. A $ (as last character of the pattern) mathing the end of a line.
  148.     5. A \<character> matching <character>.
  149.     6. A number of characters enclosed in [] pairs matching any of these
  150.        characters. A list of characters can be indicated by a '-'. So
  151.        [a-z] matches any letter of the alphabet. If the first character
  152.        after the '[' is a '^' then the set is negated (matching none of
  153.        the characters).
  154.        A ']', '^' or '-' can be escaped by putting a '\' in front of it.
  155.        Of course this means that a \ must be represented by \\.
  156.     7. If one of the expressions as described in 1-6 is followed by a
  157.        '*' than that expressions matches a sequence of 0 or more of
  158.        that expression.
  159.  
  160.     Parsing of regular expression is done in two phases. In the first phase
  161.     the expression is compiled into a more comprehensible form. In the second
  162.     phase the actual matching is done. For more details see 3.6.
  163.  
  164.  
  165.  3. Implementation of mined.
  166.  
  167.     3.1 Data structures.
  168.  
  169.     The main data structures are as follows. The whole file is kept in a
  170.     double linked list of lines. The LINE structure looks like this:
  171.  
  172.         typedef struct Line {
  173.             struct Line * next;
  174.             struct Line * prev;
  175.             char * text;
  176.             unsigned char shift_count;
  177.         } LINE;
  178.  
  179.     Each line entry contains a pointer to the next line, a pointer to the
  180.     previous line and a pointer to the text of that line. A special field
  181.     shift_count contains the number of shifts (in units of SHIFT_SIZE)
  182.     that is performed on that line. The total size of the structure is 7
  183.     bytes so a file consisting of 1000 empty lines will waste a lot of
  184.     memory. A LINE structure is allocated for each line in the file. After
  185.     that the number of characters of the line is counted and sufficient
  186.     space is allocated to store them (including a linefeed and a '\0').
  187.     The resulting address is assigned to the text field in the structure.
  188.  
  189.     A special structure is allocated and its address is assigned to the
  190.     variable header as well as the variable tail. The text field of this
  191.     structure is set to NIL_PTR. The tail->prev of this structure points
  192.     to the last LINE of the file and the header->next to the first LINE.
  193.     Other LINE * variables are top_line and bot_line which point to the
  194.     first line resp. the last line on the screen.
  195.     Two other variables are important as well. First the LINE * cur_line,
  196.     which points to the LINE currently in use and the char * cur_text,
  197.     which points to the character at which the cursor stands.
  198.     Whenever an ASCII character is typed, a new line is build with this
  199.     character inserted. Then the old data space (pointed to by
  200.     cur_line->text) is freed, data space for the new line is allocated and
  201.     assigned to cur_line->text.
  202.  
  203.     Two global variables called x and y represent the x and y coordinates
  204.     from the cursor. The global variable nlines contains the number of
  205.     lines in the file. Last_y indicates the maximum y coordinate of the
  206.     screen (which is usually SCREENMAX).
  207.  
  208.     A few strings must be initialized by hand before compiling mined.
  209.     These string are enter_string, which is printed upon entering mined,
  210.     rev_video (turn on reverse video), normal_video, rev_scroll (perform a
  211.     reverse scroll) and pos_string. The last string should hold the
  212.     absolute position string to be printed for cursor motion. The #define
  213.     X_PLUS and Y_PLUS should contain the characters to be added to the
  214.     coordinates x and y (both starting at 0) to finish cursor positioning.
  215.  
  216.     3.2 Starting up.
  217.  
  218.     Mined can be called with or without argument and the function
  219.     load_file() is called with these arguments. load_file() checks
  220.     if the file exists if it can be read and if it is writable and
  221.     sets the writable flag accordingly. If the file can be read,
  222.     load_file() reads a line from the file and stores this line into
  223.     a structure by calling install_line() and line_insert() which
  224.     installs the line into the double linked list, until the end of the
  225.     file is reached.
  226.     Lines are read by the function get_line(), which buffers the
  227.     reading in blocks of SCREEN_SIZE. Load_file() also initializes the
  228.     LINE * variables described above.
  229.  
  230.     3.3 Moving around.
  231.  
  232.     Several commands are implemented for moving through the file.
  233.     Moving up (UP), down (DN) left (LF) and right (RT) are done by the
  234.     arrow keys. Moving one line below the screen scrolls the screen one
  235.     line up. Moving one line above the screen scrolls the screen one line
  236.     down. The functions forward_scroll() and reverse_scroll() take care
  237.     of that.
  238.     Several other move functions exist: move to begin of line (BL), end of
  239.     line (EL) top of screen (HIGH), bottom of screen (LOW), top of file
  240.     (HO), end of file (EF), scroll one page down (PD), scroll one page up
  241.     (PU), scroll one line down (SD), scroll one line up (SU) and move to a
  242.     certain line number (GOTO).
  243.     Two functions called MN() and MP() each move one word further or
  244.     backwards. A word is a number of non-blanks seperated by a space, a
  245.     tab or a linefeed.
  246.  
  247.     3.4 Modifying text.
  248.  
  249.     The modifying commands can be separated into two modes. The first
  250.     being inserting text, and the other deleting text. Two functions are
  251.     created for these purposes: insert() and delete(). Both are capable
  252.     of deleting or inserting large amounts of text as well as one
  253.     character. Insert() must be given the line and location at which
  254.     the text must be inserted. Is doesn't make any difference whether this
  255.     text contains linefeeds or not. Delete() must be given a pointer to
  256.     the start line, a pointer from where deleting should start on that
  257.     line and the same information about the end position. The last
  258.     character of the file will never be deleted. Delete() will make the
  259.     necessary changes to the screen after deleting, but insert() won't.
  260.     The functions for modifying text are: insert one char (S), insert a
  261.     file (file_insert(fd)), insert a linefeed and put cursor back to
  262.     end of line (LIB), delete character under the cursor (DCC), delete
  263.     before cursor (even linefeed) (DPC), delete next word (DNW), delete
  264.     previous word (DPW) and delete to end of line (if the cursor is at
  265.     a linefeed delete line) (DLN).
  266.  
  267.     3.5 Yanking.
  268.  
  269.     A few utilities are provided for yanking pieces of text. The function
  270.     MA() marks the current position in the file. This is done by setting
  271.     LINE * mark_line and char * mark_text to the current position. Yanking
  272.     of text can be done in two modes. The first mode just copies the text
  273.     from the mark to the current position (or visa versa) into a buffer
  274.     (YA) and the second also deletes the text (DT). Both functions call
  275.     the function set_up() with the delete flag on or off. Set_up()
  276.     checks if the marked position is still a valid one (by using
  277.     check_mark() and legal()), and then calls the function yank() with
  278.     a start and end position in the file. This function copies the text
  279.     into a scratch_file as indicated by the variable yank_file. This
  280.     scratch_file is made unique by the function scratch_file(). At the end
  281.     of copying yank will (if necessary) delete the text. A global flag
  282.     called yank_status keeps track of the buffer (or file) status. It is
  283.     initialized on NOT_VALID and set to EMPTY (by set_up()) or VALID (by
  284.     yank()). Several things can be done with the buffer. It can be
  285.     inserted somewhere else in the file (PT) or it can be copied into
  286.     another file (WB), which will be prompted for.
  287.  
  288.     3.6 Search and replace routines.
  289.  
  290.     Searching for strings and replacing strings are done by regular
  291.     expressions. For any expression the function compile() is called
  292.     with as argument the expression to compile. Compile() returns a
  293.     pointer to a structure which looks like this:
  294.  
  295.         typedef struct regex {
  296.             union {
  297.                 char * err_mess;
  298.                 int * expression;
  299.             } result;
  300.             char status;
  301.             char * start_ptr;
  302.             char * end_ptr;
  303.         } REGEX;
  304.  
  305.     If something went wrong during compiling (e.g. an illegal expression
  306.     was given), the function reg_error() is called, which sets the status
  307.     field to REG_ERROR and the err_mess field to the error message. If the
  308.     match must be anchored at the beginning of the line (end of line), the
  309.     status field is set to BEGIN_LINE (END_LINE). If none of these special
  310.     cases are true, the field is set to 0 and the function finished() is
  311.     called. Finished() allocates space to hold the compiled expression
  312.     and copies this expression into the expression field of the union
  313.     (bcopy()). Matching is done by the routines match() and line_check().
  314.     Match() takes as argument the REGEX * program, a pointer to the
  315.     startposition on the current line, and a flag indicating FORWARD or
  316.     REVERSE search. Match() checks out the whole file until a match is
  317.     found. If match is found it returns a pointer to the line in which the
  318.     match was found else it returns a NIL_LINE. Line_check() takes the
  319.     same arguments, but return either MATCH or NO_MATCH.
  320.     During checking, the start_ptr and end_ptr fields of the REGEX
  321.     structure are assigned to the start and end of the match.
  322.     Both functions try to find a match by walking through the line
  323.     character by character. For each possibility, the function
  324.     check_string() is called with as arguments the REGEX * program and the
  325.     string to search in. It starts walking through the expression until
  326.     the end of the expression or the end of the string is reached.
  327.     Whenever a * is encountered, this position of the string is marked,
  328.     the maximum number of matches are performed and the function star()
  329.     is called in order to try to find the longest match possible. Star()
  330.     takes as arguments the REGEX program, the current position of the
  331.     string, the marked position and the current position of the expression
  332.     Star() walks from the current position of the string back to the
  333.     marked position, and calls string_check() in order to find a match.
  334.     It returns MATCH or NO_MATCH, just as string_check() does.
  335.     Searching is now easy. Both search routines (forward (SF) and
  336.     backwards search (SR)) call search() with an apropiate message and a
  337.     flag indicating FORWARD or REVERSE search. Search() will get an
  338.     expression from the user by calling get_expression(). Get_expression()
  339.     returns a pointer to a REGEX structure or NIL_REG upon errors and
  340.     prompts for the expression. If no expression if given, the previous is
  341.     used instead. After that search will call match(), and if a match is
  342.     found, we can move to that place in the file by the functions find_x()
  343.     and find_y() which will find display the match on the screen.
  344.     Replacing can be done in two ways. A global replace (GR) or a line
  345.     replace (LR). Both functions call change() with a message and a flag
  346.     indicating global or line replacement. Change() will prompt for the
  347.     expression and for the replacement. Every & in the replacement pattern
  348.     means substitute the match instead. An & can be escaped by a \. When
  349.     a match is found, the function substitute() will perform the
  350.     substitution.
  351.  
  352.     3.6 Miscellaneous commands.
  353.  
  354.     A few commands haven't be discussed yet. These are redraw the screen
  355.     (RD) fork a shell (SH), print file status (FS), write file to disc
  356.     (WT), insert a file at current position (IF), leave editor (XT) and
  357.     visit another file (VI). The last two functions will check if the file
  358.     has been modified. If it has, they will ask if you want to save the
  359.     file by calling ask_save().
  360.     The function REPT() will repeat a command n times. It will prompt for
  361.     the number. Aborting the loop can be done by sending the ^\ signal.
  362.  
  363.     3.7 Utility functions.
  364.  
  365.     Several functions exists for internal use. First allocation routines:
  366.     alloc(bytes) and newline() will return a pointer to free data space
  367.     if the given size. If there is no more memory available, the function
  368.     panic() is called.
  369.     Signal handling: The only signal that can be sent to mined is the
  370.     SIGQUIT signal. This signal, functions as a general abort command.
  371.     Mined will abort if the signal is given during the main loop. The
  372.     function abort_mined() takes care of that.
  373.     Panic() is a function with as argument a error message. It will print
  374.     the message and the error number set by the kernel (errno) and will
  375.     ask if the file must be saved or not. It resets the terminal
  376.     (raw_mode()) and exits.
  377.     String handling routines like copy_string(to, from), length_of(string)
  378.     and build_string(buffer, format, arg1, arg2, ...). The latter takes
  379.     a description of the string out out the format field and puts the
  380.     result in the buffer. (It works like printf (3), but then into a
  381.     string). The functions status_line(string1, string2), error(string1,
  382.     string2), clear_status() and bottom_line() all print information on
  383.     the status line.
  384.     Get_string(message, buffer) reads a string and getchar() reads one
  385.     character from the terminal.
  386.     Num_out((long) number) prints the number into a 11 digit field
  387.     without leading zero's. It returns a pointer to the resulting string.
  388.     File_status() prints all file information on the status line.
  389.     Set_cursor(x, y) prints the string to put the cursor at coordinates
  390.     x and y.
  391.     Output is done by four functions: writeline(fd,string), clear_buffer()
  392.     write_char(fd, c) and flush_buffer(fd). Three defines are provided
  393.     to write on filedescriptor STD_OUT (terminal) which is used normally:
  394.     string_print(string), putchar(c) and flush(). All these functions
  395.     use the global I/O buffer screen and the global index for this array
  396.     called out_count. In this way I/O can be buffered, so that reads or
  397.     writes can be done in blocks of SCREEN_SIZE size.
  398.     The following functions all handle internal line maintenance. The
  399.     function proceed(start_line, count) returns the count'th line after
  400.     start_line.  If count is negative, the count'th line before the
  401.     start_line is returned. If header or tail is encountered then that
  402.     will be returned. Display(x, y, start_line, count) displays count
  403.     lines starting at coordinates [x, y] and beginning at start_line. If
  404.     the header or tail is encountered, empty lines are displayed instead.
  405.     The function reset(head_line, ny) reset top_line, last_y, bot_line,
  406.     cur_line and y-coordinate. This is not a neat way to do the
  407.     maintenance, but it sure saves a lot of code. It is usually used in
  408.     combination with display().
  409.     Put_line(line, offset, clear_line), prints a line (skipping characters
  410.     according to the line->shift_size field) until XBREAK - offset
  411.     characters are printed or a '\n' is encountered. If clear_line is
  412.     TRUE, spaces are printed until XBREAK - offset characters.
  413.     Line_print(line) is a #define from put_line(line, 0, TRUE).
  414.     Moving is done by the functions move_to(x, y), move_addres(address)
  415.     and move(x, adress, y). This function is the most important one in
  416.     mined. New_y must be between 0 and last_y, new_x can be about
  417.     anything, address must be a pointer to an character on the current
  418.     line (or y). Move_to() first adjust the y coordinate together with
  419.     cur_line. If an address is given, it finds the corresponding
  420.     x-coordinate. If an new x-coordinate was given, it will try to locate
  421.     the corresponding character. After that it sets the shift_count field
  422.     of cur_line to an apropiate number according to new_x. The only thing
  423.     left to do now is to assign the new values to cur_line, cur_text, x
  424.     and y.
  425.  
  426.  4. Summary of commands.
  427.  
  428.     See seperate file mined.help .
  429.  
  430. +===========================================================================+
  431.